import select
import socket
import traceback
import sys
import queue
import richiesta
kbyte = 1024
pacchetto = 4*kbyte	#in byte
#il pacchetto deve essere almeno più grande degli header di una richiesta GET/POST
#uso lo standard di apache, 8k
connessioni = []
datiConnessione = {}
def scrivi(connessione, dati, lunghezzaTot = -1):
	global pacchetto
	if lunghezzaTot == -1:
		lunghezzaTot = len(dati)
	inviati = 0
	if connessione.fileno() < 0:
		return
	try:
		while inviati < lunghezzaTot:
			#r,w,e = select.select ([],[connessione],[])
			inviatiOra = connessione.send(dati[inviati:inviati+pacchetto])
			if inviatiOra == 0:
				return
			inviati += inviatiOra
	except (BrokenPipeError, OSError):
		chiudi(connessione)

def chiudi(connessione):
	print(str(connessione.fileno())+": chiusura")
	#raise Exception("chiuso qui")
	#traceback.print_stack(limit=5)
	fileno = connessione.fileno()
	try:
		connessioni.remove(connessione)
		datiConnessione.pop(fileno)
	except ValueError:
		pass
	try:
		connessione.shutdown(socket.SHUT_WR)
		connessione.close()
	except:
		pass

def threadBloccante(req,metodo,testQueue=None):
	global pacchetto
	output = ""
	connessione = req.connessione
	datiPrecedenti = None
	avanzati = bytes()
	iteration= 0
	try:
		while True:
			get = None
			if len(avanzati) == 0 and testQueue != None:
				try:
					get = testQueue.get_nowait()
					if get != None and get.destinatario != connessione.fileno():
						get = None
						testQueue.put(get)
				except queue.Empty: 
					pass
			if len(avanzati) == 0 and not get:
				#select blocca tutto finché non ci sono dati
				r,w,e = select.select([connessione],[],[connessione],2)
				if len(e) != 0:
					return
				if len(r) == 0:
					continue
				data = connessione.recv(pacchetto)
				if len(data) == 0:
					#una receive di lunghezza 0 significa fine della connessione
					chiudi(connessione)
					return
			elif get:
				print("A TRADIMENTO!")
				data = get.payload
			else:
				data = avanzati
			if data:
				metodo, datiPrecedenti, avanzati = metodo(data, req, datiPrecedenti, None)
				if not metodo:
					chiudi(connessione)
					return
			iteration +=1
	except Exception as e:
		chiudi(connessione)
		traceback.print_exc()
		#print("PING!")
		sys.exit()

class DatiConn:
	def __init__(self,connessione):
		self.connessione = connessione
		self.datiPrecedenti = None
		self.datiAvanzati = bytes()
		self.metodo = richiesta.recv
		self.req = None
	def __get__(self):
		return self.connessione
